#pragma once
#include "sysdef.h"
#include "types.h"

#   ifdef WINDOWS
#   include <windows.h>
#       define  M_ATOMIC  volatile
#       define  AtomicIntegerFetchAdd32(a,b)        (LONG)InterlockedExchangeAdd((LONG *)(a),(LONG)(b))
#       define  AtomicIntegerFetchAdd64(a,b)        (LONGLONG)InterlockedExchangeAdd64((LONGLONG *)(a),(LONGLONG)(b))

#       if (WINVER >= 0x0602)
#       define  AtomicIntegerSet8(d,n)              (char)InterlockedExchange8((char*)(d), (char)(n))
#       define  AtomicIntegerSet16                  (SHORT)InterlockedExchange16((SHORT*)(d), (SHORT)(n))
#       else    
        
#       endif

#       define  AtomicIntegerSet32(d,n)             (LONG)InterlockedExchange((LONG*)(d),(LONG)(n))
#       define  AtomicIntegerSet64(d,n)             (LONGLONG) InterlockedExchange64((LONGLONG*)(d),(LONGLONG)(n))

#       define  AtomicIntegerCompareAndSet32(d,c,n) (LONG)InterlockedCompareExchange((LONG*)(d),(LONG)(n),(LONG)(c))
#       define  AtomicIntegerCompareAndSet64(d,c,n) (LONGLONG)InterlockedCompareExchange64((LONGLONG*) d,(LONGLONG)n,  (LONGLONG)c)

#   if defined(_WIN64)
#       define  AtomicIntegerAnd8(d,v)              (char)InterlockedAnd8((char*)(d),(char)(v))
#       define  AtomicIntegerAnd16(d,v)             (SHORT)InterlockedAnd16((SHORT*)(d),(SHORT)(v))
#       define  AtomicIntegerAnd32(d,v)             (LONG)InterlockedAnd((LONG*)(d),(LONG)(v))
#       define  AtomicIntegerAnd64(d,v)             (LONGLONG)InterlockedAnd64((LONGLONG*)(d),(LONGLONG)(v))
#       define  AtomicIntegerXor8(d,v)              (char)InterlockedXor8((char*)(d),(char)(v))
#       define  AtomicIntegerXor16(d,v)             (SHORT)InterlockedXor16((SHORT*)(d),(SHORT)(v))
#       define  AtomicIntegerXor32(d,v)             (LONG)InterlockedXor((LONG*)(d),(LONG)(v))
#       define  AtomicIntegerXor64(d,v)             (LONGLONG) InterlockedXor64((LONGLONG*)(d),(LONGLONG)(v))
#       define  AtomicIntegerOr8(d,v)               (char)InterlockedOr8((char*)(d),(char)(v))
#       define  AtomicIntegerOr16(d,v)              (SHORT)InterlockedOr16((SHORT*)(d),(SHORT)(v))     
#       define  AtomicIntegerOr32(d,v)              (LONG)InterlockedOr((LONG*)(d),(LONG)(v))
#       define  AtomicIntegerOr64(d,v)              (LONGLONG)InterlockedOr64((LONGLONG*)(d),(LONGLONG)(v))
#   else
#       define  AtomicIntegerAnd8(d,v)              (char)_InterlockedAnd8((char*)(d),(char)(v))
#       define  AtomicIntegerAnd16(d,v)             (SHORT)_InterlockedAnd16((SHORT*)(d),(SHORT)(v))
#       define  AtomicIntegerAnd32(d,v)             (LONG)_InterlockedAnd((LONG*)(d),(LONG)(v))
#       define  AtomicIntegerXor8(d,v)              (char)_InterlockedXor8((char*)(d),(char)(v))
#       define  AtomicIntegerAnd64(d,v)             (LONGLONG)InterlockedAnd64((LONGLONG*)(d),(LONGLONG)(v))
#       define  AtomicIntegerXor16(d,v)             (SHORT)_InterlockedXor16((SHORT*)(d),(SHORT)(v))
#       define  AtomicIntegerXor32(d,v)             (LONG)_InterlockedXor((LONG*)(d),(LONG)(v))
#       define  AtomicIntegerXor64(d,v)             (LONGLONG) InterlockedXor64((LONGLONG*)(d),(LONGLONG)(v))
#       define  AtomicIntegerOr8(d,v)               (char)_InterlockedOr8((char*)(d),(char)(v))
#       define  AtomicIntegerOr16(d,v)              (SHORT)_InterlockedOr16((SHORT*)(d),(SHORT)(v))     
#       define  AtomicIntegerOr32(d,v)              (LONG)_InterlockedOr((LONG*)(d),(LONG)(v))
#       define  AtomicIntegerOr64(d,v)              (LONGLONG)InterlockedOr64((LONGLONG*)(d),(LONGLONG)(v))
 
 #   endif

#       define  AtomicPointerSet(d,n)               (PVOID)InterlockedExchangePointer((PVOID*)(d),(PVOID)(n))
#       define  AtomicPointerCompareAndSet(d,c,n)   (PVOID)InterlockedCompareExchangePointer((PVOID*)(d),(PVOID)(n),(PVOID)(c))

#   else
#       define  M_ATOMIC

#       define AtomicIntegerFetchAdd32              __sync_fetch_and_add
#       define AtomicIntegerFetchAdd64              __sync_fetch_and_add

#       define AtomicIntegerSet32                   __sync_lock_test_and_set
#       define AtomicIntegerSet64                   __sync_lock_test_and_set
#       define AtomicCompareAndSet32                __sync_val_compare_and_swap
#       define AtomicCompareAndSet64                __sync_val_compare_and_swap

#       define  AtomicIntegerAnd8                   __sync_fetch_and_and
#       define  AtomicIntegerAnd16                  __sync_fetch_and_and
#       define  AtomicIntegerAnd32                  __sync_fetch_and_and
#       define  AtomicIntegerAnd64                  __sync_fetch_and_and
#       define  AtomicIntegerXor8                   __sync_fetch_and_xor
#       define  AtomicIntegerXor16                  __sync_fetch_and_xor
#       define  AtomicIntegerXor32                  __sync_fetch_and_xor
#       define  AtomicIntegerXor64                  __sync_fetch_and_xor
#       define  AtomicIntegerOr8                    __sync_fetch_and_or
#       define  AtomicIntegerOr16                   __sync_fetch_and_or    
#       define  AtomicIntegerOr32                   __sync_fetch_and_or
#       define  AtomicIntegerOr64                   __sync_fetch_and_or

#       define  AtomicPointerSet(d,n)               (PVOID)__sync_lock_test_and_set((PLONG)(d),(LONG)(n))
#       define  AtomicPointerCompareAndSet(d,c,n)   (PVOID)__sync_val_compare_and_swap((PVOID*)(d),(PVOID)(n),(PVOID)(c))


#   endif
